package de.jmda.gen.java.impl;

import java.util.List;

import javax.validation.constraints.NotNull;

import de.jmda.gen.Generator;
import de.jmda.gen.GeneratorException;
import de.jmda.gen.java.ClassGenerator;
import de.jmda.gen.java.InstanceFieldDeclarationGenerator;
import de.jmda.gen.java.InstanceMethodDeclarationGenerator;
import de.jmda.gen.java.ModifiersUtil.VisibilityModifier;
import de.jmda.gen.java.StaticMethodDeclarationGenerator;
import de.jmda.gen.java.TypeModifiersGenerator;

/**
 * @author roger.jmda@gmail.com
 */
public class DefaultClassGenerator
		extends DefaultCompilationUnitTypeGenerator
		implements ClassGenerator
{
	private MainMethodGenerator mainMethodGenerator;

	public StaticMethodDeclarationGenerator getMainMethodGenerator()
	{
		return mainMethodGenerator;
	}

	public void setMainMethodGenerator(MainMethodGenerator generator)
	{
		this.mainMethodGenerator = generator;
	}

	@Override
  public List<Generator> getGeneratorComponents()
  {
		if (mainMethodGenerator != null)
		{
      List<StaticMethodDeclarationGenerator> generators =
      		 getCompilationUnitTypeDeclarationGenerator()
      		.getDeclaredTypeGenerator()
      		.getTypeBodyGenerator()
      		.demandStaticPartsGenerator()
      		.demandPrimaryStaticPartGenerator()
      		.getStaticMethodDeclarationsGenerator()
      		.getGenerators();

      if (false == generators.contains(mainMethodGenerator))
      {
      	generators.add(mainMethodGenerator);
      }
		}

		return super.getGeneratorComponents();
  }

	@Override
  public void setClassName(@NotNull String className)
  {
		setCompilationUnitTypeName(className);
  }

	@Override
	@NotNull
  public String getClassName() throws GeneratorException
  {
	  return getCompilationUnitTypeName();
  }

	@Override
  public void setExtendsClause(String extendsClause)
  {
		getCompilationUnitTypeDeclarationGenerator().getDeclaredTypeGenerator()
		                                            .demandExtendsClauseGenerator()
		                                            .setExtendsClause(extendsClause);
  }

	@Override
  public StringBuffer getExtendsClause() throws GeneratorException
  {
		return
				getCompilationUnitTypeDeclarationGenerator()
						.getDeclaredTypeGenerator()
						.demandExtendsClauseGenerator()
						.getExtendsClause();

  }

	@Override
  public void setImplementsClause(String implementsClause)
  {
		getCompilationUnitTypeDeclarationGenerator().getDeclaredTypeGenerator()
		                                            .demandImplementsClauseGenerator()
		                                            .setImplementsClause(implementsClause);
  }

	@Override
  public StringBuffer getImplementsClause() throws GeneratorException
  {
		return
				getCompilationUnitTypeDeclarationGenerator()
						.getDeclaredTypeGenerator()
						.demandImplementsClauseGenerator()
						.getImplementsClause();

  }

	@Override
  public void setMainMethod(String methodBody)
  {
		if (mainMethodGenerator == null)
		{
			mainMethodGenerator = new MainMethodGenerator(methodBody);
		}
		else
		{
			mainMethodGenerator.getDeclaredMethodGenerator()
			                   .setMethodBody(methodBody);
		}
  }

	@Override
  public String getMainMethod() throws GeneratorException
  {
		// TODO make null safe
	  return mainMethodGenerator.generate().toString();
  }

	@Override
  public void addAnnotation(Class<?> annotation, StringBuffer parameters)
  {
		getCompilationUnitTypeDeclarationGenerator()
				.demandAnnotationStatementsGenerator()
				.getAnnotationStatementGenerators()
				.add(new DefaultAnnotationStatementGenerator(annotation, parameters));
  }

	@Override
  public void addInstanceMethodGenerator(
  		InstanceMethodDeclarationGenerator generator)
  {
		getCompilationUnitTypeDeclarationGenerator()
				.getDeclaredTypeGenerator()
				.getTypeBodyGenerator()
				.demandInstanceMethodDeclarationsGenerator().add(generator);
  }

	@Override
  public void addInstanceFieldGenerator(
  		InstanceFieldDeclarationGenerator generator)
  {
		getCompilationUnitTypeDeclarationGenerator()
				.getDeclaredTypeGenerator()
				.getTypeBodyGenerator()
				.demandInstanceFieldDeclarationsGenerator().add(generator);
  }

	@Override
  public void setVisibility(VisibilityModifier modifier)
  {
		TypeModifiersGenerator modifiersGenerator =
				getCompilationUnitTypeDeclarationGenerator()
						.getDeclaredTypeGenerator()
						.demandModifiersGenerator();
		
		if (modifier == VisibilityModifier.DEFAULT)
		{
			// do nothing
		}
		else if (modifier == VisibilityModifier.PRIVATE)
		{
			modifiersGenerator.setPrivate(true);
		}
		else if (modifier == VisibilityModifier.PROTECTED)
		{
			modifiersGenerator.setProtected(true);
		}
		else if (modifier == VisibilityModifier.PUBLIC)
		{
			modifiersGenerator.setPublic(true);
		}
  }
}